package org.example.expansionpoint.instantiationAwareBeanPostProcessor;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * @Description:
 */
@SpringBootApplication
@Slf4j
public class TestInstantiationAwareBeanPostProcessor {

    private static final String EXAMPLE_BEAN_NAME = "example_bean_name";

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(TestInstantiationAwareBeanPostProcessor.class, args);
        Example example = context.getBean(Example.class);
        System.out.println(example.str); // 小黑
        System.out.println(example.age); // 12
        context.close();
    }

    @Component
    static class Dependence {
        public Dependence() {
            System.out.println("2. 执行了 Dependence 的无参构造");
        }
    }

    @Data
    static class Example {
        private String str = "example";
        private Integer age;
        private Dependence dependence;

        public void setAge(Integer age) {
            System.out.println("11. 执行了 Example  属性注入");
            this.age = age;
        }

        @Autowired
        public void setDependence(Dependence dependence) {
            System.out.println("Example 注入 Dependence");
            this.dependence = dependence;
        }

        public void setStr(String str) {
            System.out.println("11. 执行了 Example  属性注入");
            this.str = str;
        }

        public Example() {
            System.out.println("8. 执行了 Example 的无参构造");
        }

        public void init() {
            System.out.println("13. 执行了 Example init() 方法");
        }
    }

    @Configuration
    static class TestConfiguration {
        @Bean(initMethod = "init", value = EXAMPLE_BEAN_NAME)
        public Example example() {
            return new Example();
        }
    }

    @Component
    static class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
        /**
         * 实例化前执行
         */
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            if (Dependence.class.equals(beanClass)) {
                System.out.println("1. 执行了 Dependence  postProcessBeforeInstantiation() 方法");
            }
            if (EXAMPLE_BEAN_NAME.equals(beanName)) {
                System.out.println("7. 执行了 Example postProcessBeforeInstantiation() 方法");
            }
            // 是否返回其他 Bean 实例？可以返回代理对象，阻止默认实例化
            return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
        }

        /**
         * 实例化后执行
         */
        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            if (bean instanceof Dependence) {
                System.out.println("3. 执行了 Dependence  postProcessAfterInstantiation() 方法");
            }
            if (EXAMPLE_BEAN_NAME.equals(beanName)) {
                System.out.println("9. 执行了 Example postProcessAfterInstantiation() 方法");
            }
            // 是否需要依赖注入，如果返回 false，则不再执行 postProcessProperties() 方法；
            return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
        }

        /**
         * 实例化后，属性注入前执行
         */
        @Override
        public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
            if (bean instanceof Dependence) {
                System.out.println("4. 执行了 Dependence  postProcessProperties() 方法");
            }
            if (EXAMPLE_BEAN_NAME.equals(beanName)) {
                System.out.println("10. 执行了 Example postProcessProperties() 方法");
                MutablePropertyValues propertyValues = (MutablePropertyValues) pvs;
                propertyValues.add("str", "小黑");
                propertyValues.add("age", 12);
            }
            return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
        }

        /**
         * 初始化前执行
         */
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof Dependence) {
                System.out.println("5. 执行了 Dependence  postProcessProperties() 方法");
            }
            if (EXAMPLE_BEAN_NAME.equals(beanName)) {
                System.out.println("12. 执行了 Example postProcessProperties() 方法");
            }
            return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
        }

        /**
         * 初始化后执行
         */
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof Dependence) {
                System.out.println("6. 执行了 Dependence  postProcessProperties() 方法");
            }
            if (EXAMPLE_BEAN_NAME.equals(beanName)) {
                System.out.println("14. 执行了 Example postProcessProperties() 方法");
            }
            return InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
        }
    }
}
